namespace SaToken.SaToken.Application;

/// <summary>
/// 对写值的一组方法封装
/// <para> 封装 SaStorage、SaSession、SaApplication 等存取值的一些固定方法，减少重复编码 </para>
/// </summary>
/// <author>click33</author>
/// <since>1.31.0</since>
public interface ISaSetValueInterface : ISaGetValueInterface
{
    // --------- 需要子类实现的方法 

    /// <summary>
    /// 写值 
    /// </summary>
    /// <param name="key">名称</param>
    /// <param name="value">值</param>
    /// <returns>对象自身</returns>
    ISaSetValueInterface Set(string key, object value);

    /// <summary>
    /// 删值 
    /// </summary>
    /// <param name="key">要删除的key</param>
    /// <returns>对象自身</returns>
    ISaSetValueInterface Delete(string key);


    // --------- 接口提供封装的方法 

    /// <summary>
    /// 取值 (如果值为 null，则执行 fun 函数获取值，并把函数返回值写入缓存) 
    /// </summary>
    /// <typeparam name="T">返回值的类型</typeparam>
    /// <param name="key">key</param>
    /// <param name="fun">值为null时执行的函数</param>
    /// <returns>值</returns>
    public virtual T Get<T>(string key, Func<T> fun)
    {
        object value = Get(key);
        if (value == null)
        {
            value = fun();
            Set(key, value);
        }
        return (T)value;
    }

    /// <summary>
    /// 写值 (只有在此 key 原本无值的情况下才会写入)
    /// </summary>
    /// <param name="key">名称</param>
    /// <param name="value">值</param>
    /// <returns>对象自身</returns>
    public virtual ISaSetValueInterface SetByNull(string key, object value)
    {
        if (!Has(key))
        {
            Set(key, value);
        }
        return this;
    }
}